Azure App Service on Linux(PHP 8.0)で.htaccessが使えなかった
いわさです。
App Service on LinuxでランタイムにPHP8.0を選択しサイトを構築しました。
既定のドキュメントを変更するために、.htaccess
に以下の記述を行いアップロードしました。
DirectoryIndex hoge.html
しかし、ルートURLでアクセスすると、デフォルトで配置されているhostingstart.html
が表示されてしまいました。
App Service on Windowsでは既定のドキュメントに関する設定項目がありますが、Linuxにはありません。
今回のように既定のドキュメントを変更したいなどなったときはドキュメントでは.htaccess
を利用するように案内されています。
App Service の既定の PHP イメージでは Apache が使用されていて
しかし、.htaccess
の設定が効いてない感じがします。
どういうことでしょうか。
実はApp Service on Linuxではランタイムによってミドルウェアを含むイメージ部分が異なっており、PHPの場合だと8.0とそれ未満では大きく構成が違っていました。
PHPのバージョンはApp Serviceの構築時に指定、またはアプリ構成から変更が可能です。
PHP 7.4
先程と同様に、FTPで変更対象のhtmlファイルと.htaccess
をアップロードします。
今度は期待どおり、既定のドキュメントが変わりました。
少しイメージの中身を見てみましょう。
AzureポータルメニューにSSHの機能がありますので、Webブラウザでリモートアクセスします。
_____ / _ \ __________ _________ ____ / /_\ \___ / | \_ __ \_/ __ \ / | \/ /| | /| | \/\ ___/ \____|__ /_____ \____/ |__| \___ > \/ \/ \/ A P P S E R V I C E O N L I N U X Documentation: http://aka.ms/webapp-linux PHP quickstart: https://aka.ms/php-qs PHP version : 7.4.16 Note: Any data outside '/home' is not persisted root@589cec522b63:/home# ps -x PID TTY STAT TIME COMMAND 1 ? SNs 0:00 /bin/sh /opt/startup/startup.sh 25 ? SNs 0:00 /usr/sbin/sshd 31 ? SN 0:00 apache2 -DFOREGROUND 48 ? SNs 0:00 sshd: root@pts/0 50 pts/0 SNs 0:00 -bash 53 pts/0 RN+ 0:00 ps -x
実行プロセスを確認してみると、Apacheが起動されていますね。
こちらについてはドキュメントのとおり.htaccess
を使えば良さそうです。
PHP 8.0
解析
まずは同じようにSSHアクセスし、実行プロセスを確認してみます。
_____ / _ \ __________ _________ ____ / /_\ \___ / | \_ __ \_/ __ \ / | \/ /| | /| | \/\ ___/ \____|__ /_____ \____/ |__| \___ > \/ \/ \/ A P P S E R V I C E O N L I N U X Documentation: http://aka.ms/webapp-linux PHP quickstart: https://aka.ms/php-qs PHP version : 8.0.3 Note: Any data outside '/home' is not persisted root@49257a730b5f:/home# ps PID TTY TIME CMD 46 pts/0 00:00:00 bash 49 pts/0 00:00:00 ps root@49257a730b5f:/home# ps -x PID TTY STAT TIME COMMAND 1 ? SNs 0:00 /bin/bash /bin/init_container.sh 20 ? SNs 0:00 /usr/sbin/sshd 26 ? SN 0:00 /bin/sh /opt/startup/startup.sh 39 ? SNs 0:00 nginx: master process /usr/sbin/nginx 40 ? SNs 0:00 php-fpm: master process (/usr/local/etc/php-fpm.conf) 44 ? SNs 0:00 sshd: root@pts/0 46 pts/0 SNs 0:00 -bash 50 pts/0 RN+ 0:00 ps -x
Apacheが実行されていないですね。
だから.htaccess
が有効にならなかったのですね。
どうやらこちらは、nginx + php-fpm構成のようです。
では、nginx.confを確認してみましょう。
root@c24acaa2abe6:/etc/nginx# cat /etc/nginx/nginx.conf user www-data; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; events { worker_connections 10068; multi_accept on; } http { ## # Basic Settings ## sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # server_tokens off; # server_names_hash_bucket_size 64; # server_name_in_redirect off; include /etc/nginx/mime.types; default_type application/octet-stream; ## # SSL Settings ## ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE ssl_prefer_server_ciphers on; ## # Logging Settings ## access_log off; error_log /dev/stderr; ## # Gzip Settings ## gzip on; # gzip_vary on; # gzip_proxied any; # gzip_comp_level 6; # gzip_buffers 16 8k; # gzip_http_version 1.1; # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; ## # Virtual Host Configs ## include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } #mail { # # See sample authentication script at: # # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript # # # auth_http localhost/auth.php; # # pop3_capabilities "TOP" "USER"; # # imap_capabilities "IMAP4rev1" "UIDPLUS"; # # server { # listen localhost:110; # protocol pop3; # proxy on; # } # # server { # listen localhost:143; # protocol imap; # proxy on; # } #}
nginxではnginx.confは直接修正せず、サイトごとの設定をsites-enabled
配下に設定してincludeすることが多いです。
sites-available
に設定ファイルを配置し、sites-enabled
には設定ファイルへのシンボリックリンクを配置しています。
デフォルトの設定ファイル配下は以下のようになっています。
root@49257a730b5f:/home# cat /etc/nginx/sites-available/default server { #proxy_cache cache; #proxy_cache_valid 200 1s; listen 8080; listen [::]:8080; root /home/site/wwwroot; index index.php index.html index.htm; server_name example.com www.example.com; location / { index index.php index.html index.htm hostingstart.html; } # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /html/; } # Add locations of phpmyadmin here. location ~ [^/]\.php(/|$) { fastcgi_split_path_info ^(.+?\.php)(|/.*)$; fastcgi_pass 127.0.0.1:9000; include fastcgi_params; fastcgi_param HTTP_PROXY ""; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; fastcgi_param QUERY_STRING $query_string; fastcgi_intercept_errors on; fastcgi_connect_timeout 300; fastcgi_send_timeout 3600; fastcgi_read_timeout 3600; fastcgi_buffer_size 128k; fastcgi_buffers 4 256k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; } }
ここに、デフォルトドキュメントの記述がありますね。
試しに修正してみましょう。
hoge.htmlを追加し、nginx -s reload
でnginxを再起動します。
反映されましたね。 めでたしめでたし。
しかし、喜ぶのはまだ早い。
App Serviceを再起動してみましょう。
戻ってしまいました。
先程の設定ファイルを確認してみると追加した設定が消えています。
App Service起動時に毎回仮想環境を作り直しているようですね。
対応方法の検討
実行プロセスをもう一度見てみると、初期化にあたっていくつかスクリプトを実行しています。
init_container.sh
が実行されたのちに、startup.sh
が実行されています。
どうにかして初期化処理でnginx.confに割り込めそうか、それぞれのスクリプトの中身を少し見てみましょう。
root@49257a730b5f:/home# cat /bin/init_container.sh #!/bin/bash cat >/etc/motd <<EOL _____ / _ \ __________ _________ ____ / /_\ \\___ / | \_ __ \_/ __ \ / | \/ /| | /| | \/\ ___/ \____|__ /_____ \____/ |__| \___ > \/ \/ \/ A P P S E R V I C E O N L I N U X Documentation: http://aka.ms/webapp-linux PHP quickstart: https://aka.ms/php-qs PHP version : `php -v | head -n 1 | cut -d ' ' -f 2` Note: Any data outside '/home' is not persisted EOL cat /etc/motd # Get environment variables to show up in SSH session eval $(printenv | sed -n "s/^\([^=]\+\)=\(.*\)$/export \1=\2/p" | sed 's/"/\\\"/g' | sed '/=/s//="/' | sed 's/$/"/' >> /etc/profile) # starting sshd process sed -i "s/SSH_PORT/$SSH_PORT/g" /etc/ssh/sshd_config /usr/sbin/sshd appPath="/home/site/wwwroot" runFromPath="/tmp/webapp" startupCommandPath="/opt/startup/startup.sh" userStartupCommand="$@" if [ -z "$userStartupCommand" ] then userStartupCommand="php-fpm;"; else userStartupCommand="$userStartupCommand; php-fpm;" fi oryxArgs="create-script -appPath $appPath -output $startupCommandPath \ -bindPort $PORT -startupCommand '$userStartupCommand'" echo "Running oryx $oryxArgs" eval oryx $oryxArgs $startupCommandPath
スタートアップコマンドを使って、スクリプトを組み立てていますね。
root@49257a730b5f:/home# cat /opt/startup/startup.sh #!/bin/sh # Enter the source directory to make sure the script runs where the user expects cd /home/site/wwwroot export NGINX_PORT=8080 if [ -n "$PHP_ORIGIN" ] && [ "$PHP_ORIGIN" = "php-fpm" ]; then export NGINX_DOCUMENT_ROOT='/home/site/wwwroot' service nginx start else export APACHE_DOCUMENT_ROOT='/home/site/wwwroot' fi php-fpm;
なるほど。
ここのスクリプトnginxやphp-fpmを起動しつつ、間でスタートアップコマンドを実行していますね。
このタイミングで設定ファイルを変更しnginxを再起動できれば動くかもしれないです。
ちなみに、$PHP_ORIGIN
によってApacheの設定も利用できるようです。
ここで確認出来たのはドキュメントルートの変数のみですが、他にも影響があるのかもしれないです。
本日はこちらについては踏み込んでないですが、後日もう少し調べてみたいと思います。もしかしたら他のアプローチがあるのかもしれない。
今回はnginxの設定を更新する方向で進めてみましょう。
対応方法
site-enabled
用の設定ファイルを作成し、FTPで永続ストレージのルートディレクトリにでもアップロードし、スタートアップコマンドで、nginx.confにincludeされるようにしてみましょう。
ここの更新アプローチは色々方法が考えられると思いますが、今回は上述のようにFTPで設定ファイルを永続エリアにアップロードしておき、シンボリックリンクの向き先を変更しました。
割り込み用のスクリプトを用意しても良いと思いますが、今回はそのままコマンドを書きました。
App Serviceのアプリ構成の全般設定からスタートアップコマンドを指定することが出来ます。
ln -nfs /home/site/wwwroot/default /etc/nginx/sites-enabled/default; nginx -s reload
そして、App Service構築後 or 再起動後の、スタートアップスクリプトを確認してみましょう。
root@807491349dce:/home# cat /opt/startup/startup.sh #!/bin/sh # Enter the source directory to make sure the script runs where the user expects cd /home/site/wwwroot export NGINX_PORT=8080 if [ -n "$PHP_ORIGIN" ] && [ "$PHP_ORIGIN" = "php-fpm" ]; then export NGINX_DOCUMENT_ROOT='/home/site/wwwroot' service nginx start else export APACHE_DOCUMENT_ROOT='/home/site/wwwroot' fi ln -nfs /home/site/wwwroot/default /etc/nginx/sites-enabled/default; nginx -s reload; php-fpm;
良さそうですね。
ブラウザでも確認してみましょう。
設定が反映されていることを確認出来ました。
まとめ
今回は既定のドキュメントを変更しましたが、nginxのパラメータ設定はもちろん、スタートアップコマンドを活用してやるとランタイムコンテナの既定動作を色々とカスタマイズ出来そうですね。
ランタイムごとにどういう設定変更方法を取ればよいかは、実行プロセスからどういう構成を取られているのか、その構成とするとどう変更すれば良さそうか、を考えてやると良さそうです。